package org.njbdqn.ali.database;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DbUtil {
	private static String DRIVER;
	private static String URL;
	private static String USERNAME;
	private static String PASSWORD;
	private static int MAX;
	private static int INIT;
	private static String QUERY;
	
	static {
		readConfig();
	}

	private static void readConfig() {
		try {
			Properties p = new Properties();
			String path = URLDecoder.decode(DbUtil.class.getResource("/driver.properties").getPath(), "UTF-8");
			p.load(new FileInputStream(path));
			
			DRIVER = p.getProperty("driver");
			URL = p.getProperty("url");
			USERNAME = p.getProperty("username");
			PASSWORD = p.getProperty("password");
			MAX = Integer.parseInt(p.getProperty("max"));
			INIT = Integer.parseInt(p.getProperty("init"));
			QUERY = p.getProperty("query");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() {
		return Pool.getConnectionEntry().getConn();
	}
	
	public static void destroy(Connection conn) {
		Pool.destroy(conn);
	}
	
	private static class Pool{
		private static List<ConnectionEntry> list = new ArrayList<ConnectionEntry>();
		
		public static ConnectionEntry getConnectionEntry() {
			if(list.isEmpty()) {
				for(int i=0;i<INIT;i++) {
					list.add(createConnectionEntry());
				}
				ConnectionEntry entry = list.get(0);
				entry.setFree(false);
				return entry;
			}else {
				ConnectionEntry entry = null;
				for(ConnectionEntry ce:list) {
					if(ce.isFree()) {
						entry = ce;
						entry.setFree(false);
						break;
					}
				}
				if(entry == null) {
					if(list.size()<MAX) {
						entry = createConnectionEntry();
						entry.setFree(false);
						list.add(entry);
					}else {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						return getConnectionEntry();
					}
				}
				return entry;
			}
		}
		
		public static ConnectionEntry createConnectionEntry() {
			ConnectionEntry entry = new ConnectionEntry ();
			try {
				Class.forName(DRIVER);
				Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
				entry.setConn(conn);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return entry;
		}
		
		public static void destroy(Connection conn) {
			for(ConnectionEntry ce:list) {
				if(ce.getConn() == conn) {
					ce.setFree(true);
					try {
						PreparedStatement pstate = conn.prepareStatement(QUERY);
						pstate.executeQuery();
					} catch (SQLException e) {
						list.remove(ce);
						try {
							conn.close();
						} catch (SQLException e1) {
							e1.printStackTrace();
						}
					}
					break;
				}
			}
		}
	}
}
